#include "vernon_max7219.h"
#include <string.h>

#define VERNON_TAG "VERNON_MAX7219"

extern const uint64_t IMAGES[];

// 反转二进制顺序
static inline uint8_t reverse_bit_uint8(uint8_t c)
{
    c = (c & 0xaa) >> 1 | (c & 0x55) << 1;
    c = (c & 0xcc) >> 2 | (c & 0x33) << 2;
    c = (c & 0xf0) >> 4 | (c & 0x0f) << 4;
    return c;
}

static void transpose_buffer(vernon_max7219_t *handle, uint8_t chip_index, uint8_t * target_buf)
{
    // 原理是其进行转置
    uint8_t (* matrix_buffer)[handle->cascade_size] = (uint8_t(*)[handle->cascade_size])handle->matrix_buffer;
    for(uint8_t x = 0 ; x < 8; x++) // 填充目标空白缓存区的每一行
    {
        uint8_t row_buf = 0;
        for(int j = 0; j < 8; j++) // 获取每一列的二进制数到临时变量
        {
            uint8_t temp_buf = 0;
            temp_buf = matrix_buffer[j][chip_index] & (0x80 >> x); // 通过循环获取一列的二进制信息
            temp_buf = temp_buf << x; // 不管是哪列，获取到的二进制数全部移到最高位
            row_buf |= temp_buf >> j; // 再右移，把列二进制一位一位的写进uint8_t里，作为行
        }
        target_buf[x] = row_buf;
    }
}

esp_err_t vernon_max7219_init(vernon_max7219_t *handle)
{
    esp_err_t return_val = ESP_FAIL;
    if(handle == NULL){
        ESP_LOGE(VERNON_TAG, "max7219_init: invaild argument!\n");
        return ESP_FAIL;
    }

    handle->vernon_transfer.mosi_pin = handle->mosi_pin;
    handle->vernon_transfer.cs_pin = handle->cs_pin;
    handle->vernon_transfer.clk_pin = handle->clk_pin;
    handle->vernon_transfer.cascade_size = handle->cascade_size;
    handle->vernon_transfer.used_spi_id = handle->used_spi_id;
    handle->vernon_transfer.matrix_buffer = handle->matrix_buffer;

    return_val = tranfer_init(&handle->vernon_transfer);
    return return_val;
}

esp_err_t vernon_max7219_draw_buffer(vernon_max7219_t *handle, uint8_t row_pos, uint8_t coloum_pos, uint8_t number)
{
    esp_err_t return_val = ESP_FAIL;
    if(handle == NULL || coloum_pos >= 8 * handle->cascade_size || row_pos > (8 - 1)){
        ESP_LOGE(VERNON_TAG, "disp_number: invaild argument!\n");
        return ESP_FAIL;
    }

    uint8_t (* matrix_buffer)[handle->cascade_size] = (uint8_t(*)[handle->cascade_size])handle->matrix_buffer;

    uint64_t origin_word_bitmap = IMAGES[number];
    uint8_t chip_index = coloum_pos / 8;
    uint8_t selected_chip_offset = coloum_pos % 8;

    if (selected_chip_offset == 0) // 说明用户定义的列位置正好在单个屏幕上，比如0列，8列，16列等。
    {
        for (int row = 0; row < 8 && row_pos < 8; row++, row_pos++) // 因为一共八行，所以写8
        {
            uint8_t origin_bitmap_single_row = 0xff & (origin_word_bitmap >> (row * 8)); // 单独拿出每一行的二进制
            // printf("origin bitmap: %llx, bitmap:%x\n", origin_word_bitmap, reverse_bit_uint8(origin_bitmap_single_row));
            matrix_buffer[row_pos][chip_index] = reverse_bit_uint8(origin_bitmap_single_row);
        }
    }
    else
    { // 说明用户定义的列位置不在单个屏幕上，比如1列，3列，9列等。
        for (int row = 0; row < 8 && row_pos < 8; row++, row_pos++) // 因为一共八行，所以写8
        {
            uint8_t origin_bitmap_single_row = 0xff & (origin_word_bitmap >> (row * 8)); // 单独拿出每一行的二进制
            uint8_t reverse_bitmap = reverse_bit_uint8(origin_bitmap_single_row);
            uint8_t front_chip_bitmap = reverse_bitmap >> selected_chip_offset; //对一个八进制拆分到两个八进制里
            uint8_t front_chip_bitmap_mask = ~(0xFF >> selected_chip_offset);
            uint8_t back_chip_bitmap = reverse_bitmap << (8 - selected_chip_offset);
            // printf("origin bitmap: %llx, bitmap:%x\n", origin_word_bitmap, reverse_bit_uint8(origin_bitmap_single_row));
            matrix_buffer[row_pos][chip_index] = front_chip_bitmap_mask & matrix_buffer[row_pos][chip_index]; // 对之前缓存区已有的数据清零
            matrix_buffer[row_pos][chip_index] = front_chip_bitmap | matrix_buffer[row_pos][chip_index]; // 防止和之前已经写的二进制发生冲突
            if(chip_index + 1 < handle->cascade_size)
            {
                matrix_buffer[row_pos][chip_index + 1] = back_chip_bitmap;
            }
        }
    }
    return return_val;
}

esp_err_t vernon_max7219_send_buffer(vernon_max7219_t *handle){
    esp_err_t return_val = ESP_FAIL;
    if(handle == NULL){
        ESP_LOGE(VERNON_TAG, "max7219_init: invaild argument!\n");
        return ESP_FAIL;
    }
    
    /***************************************** 特殊情况 ********************************************/
    if(handle->is_anode || handle->left_source)
    {
        void * new_buffer = calloc(8 * handle->cascade_size, sizeof(uint8_t)); // 不能改变原buffer，否则下次使用会有bug
        memcpy(new_buffer, handle->matrix_buffer, 8 * handle->cascade_size);
        uint8_t (* matrix_buffer)[handle->cascade_size] = (uint8_t(*)[handle->cascade_size])new_buffer;

        // 共阳极使用
        if(handle->is_anode)
        {
            for(uint8_t i = 0; i < handle->cascade_size; i++)
            {
                uint8_t blank_buf[8] = {0};
                transpose_buffer(handle, i, blank_buf);
                for(uint8_t j = 0; j < 8; j++)
                {
                    matrix_buffer[j][i] = blank_buf[j]; //给每一个点阵赋值
                }
            }
        }

        // 左源输入使用
        if(handle->left_source)
        {
            for(int row = 0; row < 8; row ++)
            {
                for(int i = 0; i < handle->cascade_size / 2; i++)
                {
                    int temp_data = matrix_buffer[row][i];
                    matrix_buffer[row][i] = matrix_buffer[row][handle->cascade_size - i -1];
                    matrix_buffer[row][handle->cascade_size -i -1] = temp_data;
                }
            }
        }
        return_val =  transfer_send_buffer_custom(&handle->vernon_transfer, new_buffer);
        free (new_buffer);
        return return_val;
    }

    return_val = transfer_send_buffer(&handle->vernon_transfer);
    return return_val;
}

esp_err_t vernon_max7219_set_brightness(vernon_max7219_t *handle, uint8_t value)
{
    return transfer_set_brightness(&handle->vernon_transfer, value);
}